// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.system.service.impl;

import java.util.*;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.HierarchyDao;
import com.liuxinlong.modules.dao.HierarchyRelationDao;
import com.liuxinlong.modules.entity.Hierarchy;
import com.liuxinlong.modules.entity.HierarchyRelation;
import com.liuxinlong.modules.system.service.HierarchyService;
import com.liuxinlong.utils.ObjectUtils;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 层级关系service接口实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年1月26日
 */
@Service
@Slf4j
public class HierarchyServiceImpl implements HierarchyService {

    @Autowired
    private HierarchyDao hierarchyDao;

    @Autowired
    private HierarchyRelationDao hierarchyRelationDao;

    @Override
    public List<Map<String, Object>> pageHierarchyInfo(Map<String, Object> queryParam) {
        List<Hierarchy> originalList = hierarchyDao.pageHierarchyList(queryParam);
        int startNum = (int) queryParam.get("startNum");
        List<Map<String, Object>> resultList = completeResult(originalList, startNum);
        log.info("query hierarchy info list success!");
        return resultList;
    }

    @Override
    public int countHierarchy(Map<String, Object> queryParam) {
        return hierarchyDao.getHierarchyCount(queryParam);
    }

    @Override
    public void addHierarchyInfo(Hierarchy hierarchy) {
        String parentId = hierarchy.getParentId();
        int isGeneral = hierarchy.getIsGeneral();
        String id = SnowFlake.nextIdStr();
        if (isGeneral == 1) {
            List<HierarchyRelation> relationList = new ArrayList<>();
            Map<String, Map<String, String>> hierarchyMap = hierarchyDao.getHierarchyMap();
            String[] parentIdList = parentId.split(",");
            for (String item : parentIdList) {
                if (!hierarchyMap.containsKey(item)) {
                    throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，父层级不存在");
                }
                HierarchyRelation relation = new HierarchyRelation();
                relation.setId(SnowFlake.nextIdStr());
                relation.setHierarchyId(item);
                relation.setRelationId(id);
                relationList.add(relation);
            }
            hierarchyRelationDao.batchAddRelation(relationList);
            hierarchy.setLevelIndex(-1);
            hierarchy.setParentId("");
        } else {
            int currentLevel = 1;
            if (!StringUtils.equals(parentId, "0")) {
                Hierarchy parentHierarchy = hierarchyDao.selectById(parentId);
                if (ObjectUtils.isEmpty(parentHierarchy)) {
                    throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，父层级不存在");
                }
                currentLevel = parentHierarchy.getLevelIndex() + 1;
            }
            hierarchy.setLevelIndex(currentLevel);
        }

        hierarchy.setId(id);
        hierarchyDao.insert(hierarchy);
    }

    @Override
    public void updateHierarchyInfo(Hierarchy hierarchy) {
        String id = hierarchy.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，层级id不存在");
        }
        Hierarchy oldInfoHierarchy = hierarchyDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfoHierarchy)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，层级id不存在");
        }
        int isGeneral = hierarchy.getIsGeneral();
        String parentId = hierarchy.getParentId();
        if (isGeneral == 1) {
            List<HierarchyRelation> relationList = new ArrayList<>();
            Map<String, Map<String, String>> hierarchyMap = hierarchyDao.getHierarchyMap();
            String[] parentIdList = parentId.split(",");
            for (String item : parentIdList) {
                if (!hierarchyMap.containsKey(item)) {
                    throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，父层级不存在");
                }
                HierarchyRelation relation = new HierarchyRelation();
                relation.setId(SnowFlake.nextIdStr());
                relation.setHierarchyId(item);
                relation.setRelationId(id);
                relationList.add(relation);
            }
            hierarchyRelationDao.deleteRelationByRelation(id);
            hierarchyRelationDao.batchAddRelation(relationList);
            hierarchy.setLevelIndex(-1);
            hierarchy.setParentId("");
        } else {
            if (!StringUtils.equals(parentId, oldInfoHierarchy.getParentId())) {
                int currentLevel = 1;
                if (!StringUtils.equals(parentId, "0")) {
                    Hierarchy parentHierarchy = hierarchyDao.selectById(parentId);
                    if (ObjectUtils.isEmpty(parentHierarchy)) {
                        throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，父层级不存在");
                    }
                    currentLevel = parentHierarchy.getLevelIndex() + 1;
                }
                hierarchy.setLevelIndex(currentLevel);
            }
        }
        hierarchyDao.updateById(hierarchy);
    }

    @Override
    @Transactional
    public void deleteHierarchyInfo(String id) {
        hierarchyRelationDao.deleteRelation(id);
        hierarchyRelationDao.deleteRelationByRelation(id);
        hierarchyDao.deleteById(id);
    }

    @Override
    public List<String> treeQueryHierarchy(String name) {
        Set<String> set = new HashSet<>();
        List<Hierarchy> hierarchyList = hierarchyDao.getHierarchyListByName(name);
        for (Hierarchy hierarchy : hierarchyList) {
            set.add(hierarchy.getParentId());
        }
        return new ArrayList<>(set);
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始数
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<Hierarchy> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (ObjectUtil.isEmpty(originList)) {
            return resultList;
        }
        Map<String, Map<String, String>> hierarchyMap = hierarchyDao.getHierarchyMap();
        int sort = startNum + 1;
        for (Hierarchy item : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(item);
            map.put("sort", sort);
            if (item.getIsGeneral() == 1) {
                Map<String, Object> queryParam = new HashMap<>();
                queryParam.put("relationId", item.getId());
                List<HierarchyRelation> relations = hierarchyRelationDao.queryRelationList(queryParam);
                if (ObjectUtils.isEmpty(relations)) {
                    map.put("parentName", "");
                } else {
                    List<String> idList = new ArrayList<>();
                    List<String> nameList = new ArrayList<>();
                    for (HierarchyRelation relation : relations) {
                        idList.add(relation.getHierarchyId());
                        nameList.add(hierarchyMap.get(relation.getHierarchyId()).get("name"));
                    }
                    map.put("parentId", StringUtils.strip(idList.toString(), "[]").replace(" ", ""));
                    map.put("parentName", StringUtils.strip(nameList.toString(), "[]"));
                }
            } else {
                String parentId = item.getParentId();
                Map<String, String> parentInfo = hierarchyMap.get(parentId);
                if (ObjectUtil.isNotEmpty(parentInfo)) {
                    map.put("parentName", parentInfo.get("name"));
                }
            }
            map.put("actionScopeName", item.getActionScope() == 1 ? "标准" : "条款");
            resultList.add(map);
            sort++;
        }
        return resultList;
    }
}
